import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;

/**
 * ModGames (C) 2007 Pedro Miller Rabinovitch.
 * 
 * Permission is hereby granted to copy and use this material for any free or educational purpose.
 * Please do not use this for commercial purposes before letting me know (but it'll be fine).
 * 
 * Contact me via gmail, account pedromr
 * http://exodia.org
 * 
 * $Id: TextConfigReader.java 24 2007-11-28 16:19:46Z pedromr $
 */
/**
 * Reads a configuration text file.
 * 
 * @author Miller
 */
public class TextConfigReader {
	/**
	 * Properties read from the config file. Should be initialized to defaults
	 * prior to reading.
	 */
	public Hashtable properties;

	private InputStream in;

	private int c;

	public TextConfigReader() {
		properties = new Hashtable();
	}

	/**
	 * @param prior
	 *            Pre-established property hashtable. New ones will be merged
	 *            into it.
	 */
	public TextConfigReader(Hashtable prior) {
		properties = prior;
	}

	private void skipSpace() throws IOException {
		while (c == ' ' || c == '\t')
			readNextChar();
	}

	/**
	 * Reads a name into line (string ending before the ':' separator).
	 * 
	 * @param line
	 *            Target buffer
	 * @throws IOException
	 */
	private void readName(StringBuffer line) throws IOException {
		line.setLength(0);
		while (c != ':' && c != ' ' && c != '\t' && c != -1) {
			if (c == '\n') {
				System.out.println("Missing separator ':' in key name "
						+ line.toString());
				return;
			}
			line.append((char) c);
			readNextChar();
		}
		skipSpace();
	}

	/**
	 * Reads a value into line (string beginning after the colon and ending
	 * before the newline).
	 * 
	 * @param line
	 *            Target buffer
	 * @throws IOException
	 */
	private void readValue(StringBuffer line) throws IOException {
		line.setLength(0);
		while (c != '\n' && c != -1) {
			line.append((char) c);
			readNextChar();
		}
	}

	private void readNextChar() throws IOException {
		c = in.read();
		if (c == '\r')
			c = in.read();
		// System.out.println("read char [" + c + "]");
	}

	private void skipToNewLine() throws IOException {
		while (c != '\n' && c != -1) {
			// System.out.println("skipping to newline");
			readNextChar();
		}
	}

	/**
	 * Read all key,value pairs in a file into this property table
	 * 
	 * @param path
	 */
	public void readFile(String path) {
		System.out.println( ". opening file ["+path+"]" );
		in = this.getClass().getResourceAsStream(path);
		if( in == null ) {
			System.out.println( "** Problems reading file "+path );
		}
		StringBuffer line = new StringBuffer(2048);

		try {
			readNextChar();
			while (c != -1) {
				skipSpace();

				if (c == '#') {
					// skip line (comment)
					skipToNewLine();
				}

				if (c == '\n') {
					// end of line, go again
					readNextChar();
					continue;
				}

				if (c == -1) {
					break;
				}

				// read parameter name
				readName(line);
				String name = line.toString();
				// System.out.println("read name [" + line.toString() + "]");

				readNextChar(); // skip :
				skipSpace(); // get to the value

				readValue(line);
				String value = line.toString();
				// System.out.println("read value [" + line.toString() + "]");

				properties.put(name, value);

				readNextChar();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * Get an integer property value.
	 * 
	 * @param name
	 *            Property name
	 * @return Its value as an integer.
	 */
	public int getInt(String name) {
		return Integer.parseInt((String) properties.get(name));
	}

	String currentSequenceBeingRead;

	String currentSequenceValue;

	int currentSequencePosition;

	static char sequenceSeparator = ',';

	/**
	 * Prepares a parameter sequence for reading.
	 * 
	 * @param name
	 *            Name of the property to prepare reading from
	 * @return Whether the sequence is there.
	 */
	public boolean prepareSequence(String name) {
		currentSequencePosition = 0;
		currentSequenceBeingRead = name;
		
		if( !properties.containsKey(name))
			return false;
		
		currentSequenceValue = (String) properties.get(name);

		return currentSequenceBeingRead != null;
	}

	public boolean sequenceHasAvailable() {
		return (currentSequencePosition >= 0 && currentSequencePosition < currentSequenceValue
				.length());
	}

	public static void log(String msg) {
		System.out.println(msg);
	}

	/**
	 * Retrieves the next value from a sequence.
	 * 
	 * @param name
	 *            Name of the sequence or null to use the current one
	 * @return The value as a string
	 */
	public String getFromSequence(String name) {
		if (name != null && !name.equals(currentSequenceBeingRead)) {
			if (!prepareSequence(name))
				return null;
		} else if( currentSequenceValue == null )
			return null;
		
		if( currentSequencePosition >= currentSequenceValue.length() )
			return null;
		
		int end = currentSequenceValue.indexOf(sequenceSeparator,
				currentSequencePosition);

		if (end == -1) {
			if (currentSequencePosition < currentSequenceValue.length())
				end = currentSequenceValue.length();
			else
				return null;
		}

		// This is hardly my proudest moment. >:P
		String res = currentSequenceValue.substring(currentSequencePosition,
				end);
		currentSequencePosition = end + 1;

		return res;
	}

	public int getIntFromSequence(String name) throws IllegalArgumentException {
		String val = getFromSequence(name);
		
		return Integer.parseInt(val);
	}

}
